#include <windows.h>
#include "enviroment/uuid.h"

UCore::uuid_t UCore::GenerateUUID()
{
    UCore::uuid_t result;

    ::memset(result.data, 0, sizeof(uint32) * USTD_UUID_BYTE);

#ifdef _WIN32
    ::UUID uid;
    ::CoCreateGuid(&uid);

    result.data[0] = (uid.Data1 >> 24) & 0xFF;
    result.data[1] = (uid.Data1 >> 16) & 0xFF;
    result.data[2] = (uid.Data1 >> 8) & 0xFF;
    result.data[3] = (uid.Data1) & 0xFF;

    result.data[4] = (uid.Data2 >> 8) & 0xFF;
    result.data[5] = (uid.Data2) & 0xFF;

    result.data[6] = (uid.Data3 >> 8) & 0xFF;
    result.data[7] = (uid.Data3) & 0xFF;

    result.data[8] = uid.Data4[0];
    result.data[9] = uid.Data4[1];
    result.data[10] = uid.Data4[2];
    result.data[11] = uid.Data4[3];
    result.data[12] = uid.Data4[4];
    result.data[13] = uid.Data4[5];
    result.data[14] = uid.Data4[6];
    result.data[15] = uid.Data4[7];

#endif

    return result;
}

uBoolean UCore::IsValidUUID(const uuid_t &uuid)
{
    static UCore::uuid_t empty_uuid;
    ::memset(empty_uuid.data, 0, sizeof(uint32) * USTD_UUID_BYTE);
    return ::memcmp(uuid.data, empty_uuid.data, USTD_UUID_BYTE) != 0;
}

uString toString(const UCore::uuid_t &uuid)
{
    std::stringstream ss;

    ss.setf(std::ios_base::uppercase);
    ss << std::hex << std::setfill('0');

    ss << std::setw(2) << uuid.data[0];
    ss << std::setw(2) << uuid.data[1];
    ss << std::setw(2) << uuid.data[2];
    ss << std::setw(2) << uuid.data[3];
    ss << std::setw(2) << uuid.data[4];
    ss << std::setw(2) << uuid.data[5];
    ss << std::setw(2) << uuid.data[6];
    ss << std::setw(2) << uuid.data[7];
    ss << std::setw(2) << uuid.data[8];
    ss << std::setw(2) << uuid.data[9];
    ss << std::setw(2) << uuid.data[10];
    ss << std::setw(2) << uuid.data[11];
    ss << std::setw(2) << uuid.data[12];
    ss << std::setw(2) << uuid.data[13];
    ss << std::setw(2) << uuid.data[14];
    ss << std::setw(2) << uuid.data[15];

     return ss.str();
}

uBoolean operator==(const UCore::uuid_t &id1, const UCore::uuid_t &id2)
{
    return ::memcmp(id1.data, id2.data, USTD_UUID_BYTE) == 0;
}

uBoolean operator!=(const UCore::uuid_t &id1, const UCore::uuid_t &id2)
{
    return ::memcmp(id1.data, id2.data, USTD_UUID_BYTE) != 0;
}

uBoolean operator!(const UCore::uuid_t &uuid)
{
    return !UCore::IsValidUUID(uuid);
}